/**************************************************************************************************************************************
 * The main function of Crossbit, it initializes several main instances, like <code>MemoryManger</code>, <code>SimpleTCache</code>,....
 * some filters will be used if <code>OPT_LEVEL_1</code> is defined( like make O1 , see Makefile ).
 * Then it will invoke the <code>ExecutionEngine</code>'s <code>run</code> method to translate-execute the source binary code.
 *************************************************************************************************************************************/
#include "crossbit/ExecutionEngine.h"
#include "crossbit/ELFMemoryImage.h"
#include "crossbit/SimpleTCache.h"
#include "crossbit/NextUseRegAllocator.h"
#include "crossbit/ConstExpEvalFilter.h"
#include "crossbit/InstructionReorderFilter.h"
#include "crossbit/RedVMRegUpdateFilter.h"
#include "arch/mips/MIPSInterpreter.h"
#include "arch/mips/MIPSProcessorState.h"
#include "arch/mips/MIPSVBasicBlockBuilder.h"
#include "arch/mips/MIPSSyscallHandler.h"
#include "arch/mips/MIPSSignalHandler.h"
#include "arch/mips/MIPSSignalRegister.h"
#include "arch/x86/X86Translator.h"
#include "arch/x86/X86TraceManager.h"
#include "arch/x86/X86.h"

#define TCACHE_SIZE	1024*1024*10

extern char** environ;

using namespace crossbit;

int main(int argc, char *argv[])
{
    MemoryManager*	mm = MemoryManager::getInstance();
    SimpleTCache	tcache( TCACHE_SIZE, mm );

    ELFMemoryImage 	img( (XTPStr)argv[1], (XTUint32)(argc-1), (XTPStr*)&argv[1], (XTPStr*)environ );	
    MIPSProcessorState ps;
    MIPSInterpreter interp( &ps );
    MIPSVBasicBlockBuilder builder;
	MIPSSignalRegister sigrg;
#ifdef OPT_LEVEL_1
    PrintFilter                 pFilter;
    DumpFilter                  dpFilter;
    SSAFormFilter               ssaFilter;
    RedundancyEliminateFilter   reFilter;
    V0Filter                    v0Filter;
    ConstExpEvalFilter          ceFilter;
    RedVMRegUpdateFilter        rrFilter;
    CopyPropagationFilter       cpFilter;
	InstructionReorderFilter    irFilter;

  	 VFilter::registerFilter(&irFilter, VFilter::INT_BASIC_BLOCK);

//    VFilter::registerFilter(&pFilter, VFilter::INT_BASIC_BLOCK);
  	  VFilter::registerFilter(&v0Filter, VFilter::INT_BASIC_BLOCK);
//    VFilter::registerFilter(&pFilter, VFilter::INT_BASIC_BLOCK);
 	   VFilter::registerFilter(&cpFilter, VFilter::INT_BASIC_BLOCK);
//    VFilter::registerFilter(&pFilter, VFilter::INT_BASIC_BLOCK);
     VFilter::registerFilter(&ceFilter, VFilter::INT_BASIC_BLOCK);
 //   VFilter::registerFilter(&pFilter, VFilter::INT_BASIC_BLOCK);
   // VFilter::registerFilter(&rrFilter, VFilter::INT_BASIC_BLOCK);
   // VFilter::registerFilter(&dpFilter, VFilter::INT_BASIC_BLOCK);
  //  VFilter::registerFilter(&pFilter, VFilter::INT_BASIC_BLOCK);
#endif

    NextUseRegAllocator alloc( 8, X86::movwMemToReg, X86::movwRegToMem, X86::movwRegToReg, (XTUint32*)(ps.get(0)));
    X86Translator	tr( &ps, &alloc );
    X86TraceManager trace( mm );
    MIPSSyscallHandler sh(&ps, &img, &sigrg);
	MIPSSignalHandler sig(&ps, &img, mm, &trace, &interp, &builder, &tcache, &tr, &sh, &sigrg);

    ExecutionEngine ee( &img, mm, &trace, &interp, &builder, &tcache, &tr, &sh );
    ee.run();

    return 0;
}

